package krillr.Util;
import java.awt.geom.Point2D;
import java.util.*;

/**
 * KrillUtil - Mathimatical functions for use with robocode bots.
 * 
 * @author Aaron M. Krill
 * @version 0.1
 */
public class KrillUtil
{
    public static final Random rand = new Random();
    public static final double BOT_ROT_VEL = Math.toRadians(10);
    public static final double GUN_ROT_VEL = Math.toRadians(20);
    public static final double HALF_PI = Math.PI/2;
    
    /**
     * bestAngle:
     */
    public static double bestAngle(double angle) {
        double newAngle = angle;
        
        if (angle > Math.PI)
            newAngle -= (Math.PI * 2);
        else if (angle < -Math.PI)
            newAngle += (Math.PI * 2);
        
        return newAngle;
    }
    
    public static final double getDistance(double sourceXPos, double sourceYPos, double targetXPos, double targetYPos) {
        return getDistance(new Point2d(sourceXPos, sourceYPos), new Point2d(targetXPos, targetYPos));
    }
    
    public static final double getDistance(Point2d sourceLocation, Point2d targetLocation) {
        double distance = (sourceLocation.getX()-targetLocation.getX()) + (sourceLocation.getY()-targetLocation.getY());
        if(distance < 0)
            distance *= -1;
        return Math.sqrt(distance);
    }
    
    public static final double smallestToParallel(double angle) {
        if (angle > -Math.PI && angle <= Math.PI)
            return angle;
        double fixedAngle = angle;
        while (fixedAngle <= -Math.PI)
            fixedAngle += Math.PI*2;
        while (fixedAngle > Math.PI)
            fixedAngle -= Math.PI*2;
        return fixedAngle;
    }
    
    public static final double getBearing(double sourceXPos, double sourceYPos, double targetXPos, double targetYPos) {
        return getBearing(new Point2d(sourceXPos,sourceYPos), new Point2d(targetXPos,targetYPos));
    }
    
    public static final double getBearing(Point2d sourceLocation, Point2d targetLocation) {
        return Math.atan2(targetLocation.getX()-sourceLocation.getX(),targetLocation.getY()-sourceLocation.getY());
    }
    
    public static Point2d vectorToLocation(double angle, double length, Point2d sourceLocation) {
        return vectorToLocation(angle, length, sourceLocation, new Point2d(0,0));
    }
    
    public static Point2d vectorToLocation(double angle, double length, Point2d sourceLocation, Point2d targetLocation) {
        targetLocation.setLocation(sourceLocation.getX() + Math.sin(angle) * length,
                                   sourceLocation.getY() + Math.cos(angle) * length);
        return targetLocation;
    }
    
    public static int sign(double d) {
        return (d >= 0) ? 1 : -1;
    }
    
    public static double limit(double min, double value, double max) {
        return Math.max(min, Math.min(value, max));
    }
    
    public static double maxEscapeAngle(double velocity) {
        return Math.asin(8.0/velocity);
    }
    
    public static double directedGoAngle(int direction) {
        return (direction * 1.35);
    }
    
    public static double fixAngle(double degrees, int how) {
        double posDegrees = (degrees >= 0)?degrees:360-(Math.abs(degrees));
        if (how == 0) {    return (posDegrees) % 360; }
        else { return ((posDegrees + 180) % 360) - 180; }
    }
    
    public static double getBulletSpeed(double power)
    {
        return 20-power*3;
    }
    
    public static double getBulletEnergy(double speed) {
        return (20-speed)/3;
    }
}
